import { defineStore } from 'pinia'
import { store } from '@/store'
import { listDataAll, listDataAllInfo, getDicts } from '@/api/system/dict/data'

type DictItem = {
  /** 字典键值 */
  value: string | number
  /** 字典标签 */
  label: string | number
  /** 样式属性 */
  elTagType: string
  /** 回显样式 */
  elTagClass: string
}

export class Dict extends Array<DictItem> {
  /**
   * 根据value获取label
   * @param val
   * @returns label
   */
  public getLabel(val: string | number | boolean | Record<string, any>): any {
    if (typeof val == 'undefined' || typeof val == null) {
      return null
    }
    const result = this.find((item) => item.label == val || item.value == val)
    if (!result) {
      return null
    }
    return result.value == val ? result?.label : result?.value
  }
}

const useDictStore = defineStore({
  id: 'dict',
  state: () => ({
    dict: new Map(), //字典的键值，值是字符串
    dictInfo: new Map(), //详细的字典信息
    dictList: [] as String[], //字典名列表
  }),
  getters: {
    //字典的键值，当值为数字字符串，会转化为数字
    dict2: (state) => {
      const _dict = new Map()
      state.dict.forEach((value, key) => {
        const _value = value.map((item) => {
          return {
            ...item,
            value: isNaN(item.value) ? value : item.value,
          }
        })
        _dict.set(key, new Dict(..._value))
      })
      return _dict
    },
  },
  actions: {
    /**
     * 根据键获取字典值，字典value值转化为数字
     * @param args 字典名字符串参数，可以传入1个或多个，字典名从字典管理页获取
     * @returns 字典对象，键为字典名，值为字典值数组，字典值数组的结构为{value: Number | String;label: String;}
     */
    getDicts(
      ...args: (typeof this.dicList)[number][]
    ): Record<(typeof this.dicList)[number], Dict> {
      if (args.length === 0) {
        return null
      }
      const res: Partial<Record<(typeof this.dicList)[number], Dict>> = {}
      args.forEach((dictType) => {
        res[dictType] = this.dict2.get(dictType)
      })
      return res
    },
    /**
     * 根据键获取单个字典值，字典value值转化为数字
     * @param args 字典名字符串
     * @returns 字典对象，键为字典名，值为字典值数组，字典值数组的结构为{value: Number | String;label: String;}
     */
    getDict(dictType: String): Dict {
      if (dictType.length === 0) {
        return null
      }
      return this.dict2.get(dictType)
    },
    /**
     * 根据键获取字典值详情，字典value值是字符串
     * @param args 字典名字符串参数，可以传入1个或多个，字典名从字典管理页获取
     * @returns 字典对象，键为字典名，值为字典值数组，字典值数组的结构为{value: Number | String;label: String;}
     */
    getDictsOrigin(
      ...args: (typeof this.dicList)[number][]
    ): Record<(typeof this.dicList)[number], Dict> {
      if (args.length === 0) {
        return null
      }
      const res: Partial<Record<(typeof this.dicList)[number], Dict>> = {}
      args.forEach((dictType) => {
        res[dictType] = this.dict.get(dictType)
      })
      return res
    },
    /**
     * 根据键获取单个字典值详情，字典value值转化为数字
     * @param args 字典名字符串
     * @returns 字典对象，键为字典名，值为字典值数组，字典值数组的结构为{value: Number | String;label: String;}
     */
    getDictOrigin(dictType: String): Dict {
      if (dictType.length === 0) {
        return null
      }
      return this.dict.get(dictType)
    },
    /**
     * 根据字典value获取字典label，字典名从字典管理页获取
     * @param val 字典的value
     * @param dictname 字典名字符串
     * @returns 字典label
     */
    getLabel(
      val: string | number | boolean | Record<string, any>,
      dictname: (typeof this.dicList)[number]
    ): any {
      if (typeof val == 'undefined' || typeof val == null) {
        return null
      }
      const _dict = this.dict.get(dictname)
      if (!_dict) {
        return null
      }
      const result = _dict.find((item) => item.label == val || item.value == val)
      if (!result) {
        return null
      }
      return result.value == val ? result?.label : result?.value
    },
    // 设置字典的键值
    setDict(_key, value) {
      if (_key !== null && _key !== '') {
        this.dict.set(_key, value)
      }
    },
    /**
     * 根据键获取字典详细内容，即接口返回的所有内容
     * @param args 字典名字符串参数，可以传入1个或多个，字典名从字典管理页获取
     * @returns 字典对象，键为字典名，值为字典值数组，字典值数组的结构为{value: Number | String;label: String;}
     */
    getDictInfo(...args: (typeof this.dicList)[number][]): Record<
      (typeof this.dicList)[number],
      {
        value: Number | String
        label: String
      }
    > {
      const res: Partial<
        Record<
          (typeof this.dicList)[number],
          {
            value: Number | String
            label: String
          }
        >
      > = {}
      args.forEach((dictType) => {
        res[dictType] = this.dictInfo.get(dictType)
      })
      return res
    },
    // 设置字典详细内容
    setDictInfo(_key, value) {
      if (_key !== null && _key !== '') {
        this.dictInfo.set(_key, value)
      }
    },
    // 删除字典
    removeDict(_key) {
      this.dictInfo.delete(_key)
      return this.dict.delete(_key)
    },
    // 清空字典
    cleanDict() {
      this.dictInfo.clear()
      this.dict.clear()
    },
    async initDict() {
      return new Promise<HttpPaginationResponse<Array<any>>>((resolve, reject) => {
        listDataAll()
          .then((res) => {
            if (res.code === 200 && res.data) {
              for (const item of res.data) {
                item.status != 1 ? this.dictList.push(item.dictType) : ''
              }
              listDataAllInfo().then((res) => {
                const dicts = res.data
                for (const item of this.dictList) {
                  const _dict = dicts.filter((i) => i.dictType == item)
                  const _dictMap = []
                  for (const j of _dict) {
                    _dictMap.push({
                      value: j.dictValue,
                      label: j.dictLabel,
                      elTagType: j.listClass,
                      elTagClass: j.cssClass,
                    })
                  }
                  this.setDict(item, new Dict(..._dictMap))
                  this.setDictInfo(item, _dict)
                }
                resolve(this.dict)
              })
            } else {
              resolve(null)
            }
          })
          .catch((error) => {
            reject(error)
          })
      })
    },
    /**
     * 获取单个字典
     * @param dictType
     * @returns
     */
    async useDicts(dictType) {
      return new Promise<HttpPaginationResponse<Array<any>>>((resolve, reject) => {
        getDicts(dictType)
          .then((res) => {
            if (res.code === 200 && res.data) {
              const _dict = res.data
              const _dictMap = []
              for (const j of _dict) {
                _dictMap.push({
                  value: j.dictValue,
                  label: j.dictLabel,
                  elTagType: j.listClass,
                  elTagClass: j.cssClass,
                })
              }
              this.setDict(dictType, new Dict(..._dictMap))
              this.setDictInfo(dictType, _dict)
              resolve(this.dict[dictType])
            } else {
              resolve(null)
            }
          })
          .catch((error) => {
            reject(error)
          })
      })
    },
  },
})

export default useDictStore

export function useDictStoreHook() {
  return useDictStore(store)
}
